package cn.mujiankeji.mbrowser.功能.播放框.核心

import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.util.Util
import androidx.media3.database.StandaloneDatabaseProvider
import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.datasource.cache.Cache
import androidx.media3.datasource.cache.CacheDataSource
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
import androidx.media3.datasource.cache.SimpleCache
import androidx.media3.exoplayer.dash.DashMediaSource
import androidx.media3.exoplayer.hls.HlsMediaSource
import androidx.media3.exoplayer.rtsp.RtspMediaSource
import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.ProgressiveMediaSource
import cn.mujiankeji.mbrowser.工具.操作.地址操作
import cn.mujiankeji.mbrowser.数据.配置项.应用配置
import java.io.File
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSourceFactory
import androidx.media3.datasource.okhttp.OkHttpDataSource
import androidx.media3.exoplayer.hls.DefaultHlsExtractorFactory
import androidx.media3.exoplayer.hls.playlist.HlsMediaPlaylist
import androidx.media3.exoplayer.hls.playlist.HlsMultivariantPlaylist
import androidx.media3.exoplayer.hls.playlist.HlsPlaylist
import androidx.media3.exoplayer.hls.playlist.HlsPlaylistParser
import androidx.media3.exoplayer.hls.playlist.HlsPlaylistParserFactory
import androidx.media3.exoplayer.smoothstreaming.SsMediaSource
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy.FallbackOptions
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy.FallbackSelection
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy.LoadErrorInfo
import androidx.media3.exoplayer.upstream.ParsingLoadable
import cn.mujiankeji.mbrowser.工具.网络.OkHttpsUtils
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit
import cn.mujiankeji.mbrowser.功能.播放框.核心.CacheManager

@SuppressLint("UnsafeOptInUsageError")
class ExoHelper(val context : Context) {

    fun 取缓存实例() : Cache{
        return CacheManager.getCache(context)
    }
    fun 创建缓存工厂() : CacheDataSource.Factory{
        // 基础HTTP数据源
        val 上游数据源工厂 = DefaultHttpDataSource.Factory()
            .setConnectTimeoutMs(30000)  // 增加连接超时时间到30秒
            .setReadTimeoutMs(30000)     // 增加读取超时时间到30秒
            .setAllowCrossProtocolRedirects(true)
            .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") // 设置常见的User-Agent

        // 创建缓存数据源工厂
        val factory = CacheDataSource.Factory()
        factory.setCache(取缓存实例())
        factory.setUpstreamDataSourceFactory(上游数据源工厂)
        // 设置更积极的缓存策略
        factory.setFlags(
            CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR or 
            CacheDataSource.FLAG_BLOCK_ON_CACHE
        )
        factory.setCacheKeyFactory { dataSpec ->
            // 自定义缓存键生成器，解决带有变化参数的URL问题
            // 提取URL主体部分，忽略会变化的查询参数
            val url = dataSpec.uri.toString()
            val baseUrl = if (url.contains("?")) {
                url.split("?")[0]
            } else {
                url
            }
            baseUrl
        }

        return factory
    }
    fun 创建媒体源(地址 : String,协议头 : Map<String,String>?,
              自动缓存 : Boolean = true) : MediaSource{

        val contentUri = Uri.parse(地址)

        if (("rtsp" == contentUri.getScheme())){
            return RtspMediaSource.Factory().createMediaSource(MediaItem.fromUri(contentUri))
        }

        val contentType = inferContentType(地址)
        val factory: DataSource.Factory = if (自动缓存) {
            创建缓存工厂()
        } else {
            DefaultDataSourceFactory(context,getHttpDataSourceFactory(协议头))
        }

        return when (contentType) {
            C.CONTENT_TYPE_DASH -> DashMediaSource.Factory(factory)
                .setLoadErrorHandlingPolicy(object : LoadErrorHandlingPolicy {
                    override fun getFallbackSelectionFor(
                        fallbackOptions: FallbackOptions,
                        loadErrorInfo: LoadErrorInfo
                    ): FallbackSelection? {
                        return null
                    }

                    override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
                        return 10 // 重试延迟
                    }

                    override fun onLoadTaskConcluded(loadTaskId: Long) {}
                    override fun getMinimumLoadableRetryCount(dataType: Int): Int {
                        return 5 // 失败重试次数
                    }
                })
                .createMediaSource(MediaItem.fromUri(地址))
            C.CONTENT_TYPE_SS -> SsMediaSource.Factory(factory)
                .setLoadErrorHandlingPolicy(object : LoadErrorHandlingPolicy {
                    override fun getFallbackSelectionFor(
                        fallbackOptions: FallbackOptions,
                        loadErrorInfo: LoadErrorInfo
                    ): FallbackSelection? {
                        return null
                    }

                    override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
                        return 10 // 重试延迟
                    }

                    override fun onLoadTaskConcluded(loadTaskId: Long) {}
                    override fun getMinimumLoadableRetryCount(dataType: Int): Int {
                        return 5 // 失败重试次数
                    }
                })
                .createMediaSource(MediaItem.fromUri(地址))
            C.CONTENT_TYPE_HLS -> {
                // 为HLS创建自定义DataSource.Factory以应用协议头
                val hlsDataSourceFactory = if (协议头 != null && 协议头.isNotEmpty()) {
                    DataSource.Factory {
                        val dataSource = factory.createDataSource()
                        // 为每个请求添加协议头
                        协议头.forEach { (key, value) ->
                            dataSource.responseHeaders.put(key, listOf(value))
                        }
                        dataSource
                    }
                } else {
                    factory
                }
                
                HlsMediaSource.Factory(hlsDataSourceFactory)
                    .setAllowChunklessPreparation(true)
                    .setExtractorFactory(DefaultHlsExtractorFactory())
                    .setLoadErrorHandlingPolicy(object : LoadErrorHandlingPolicy {
                        override fun getFallbackSelectionFor(
                            fallbackOptions: FallbackOptions,
                            loadErrorInfo: LoadErrorInfo
                        ): FallbackSelection? {
                            return if (loadErrorInfo.errorCount < 5) null else {
                                FallbackSelection(
                                    LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK,
                                    30000
                                )
                            }
                        }

                        override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
                            val baseDelay = 200L
                            val errorCount = loadErrorInfo.errorCount.coerceAtMost(6)
                            return baseDelay * (1L shl errorCount)
                        }

                        override fun onLoadTaskConcluded(loadTaskId: Long) {}
                        override fun getMinimumLoadableRetryCount(dataType: Int): Int {
                            return when (dataType) {
                                C.DATA_TYPE_MANIFEST -> 30
                                C.DATA_TYPE_MEDIA -> 20
                                else -> 10
                            }
                        }
                    })
                    .createMediaSource(MediaItem.fromUri(地址))
            }
            C.CONTENT_TYPE_RTSP -> {
                RtspMediaSource.Factory()
                    .setLoadErrorHandlingPolicy(object : LoadErrorHandlingPolicy {
                        override fun getFallbackSelectionFor(
                            fallbackOptions: FallbackOptions,
                            loadErrorInfo: LoadErrorInfo
                        ): FallbackSelection? {
                            return null
                        }

                        override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
                            return 100 // 重试延迟
                        }

                        override fun onLoadTaskConcluded(loadTaskId: Long) {}
                        override fun getMinimumLoadableRetryCount(dataType: Int): Int {
                            return 10 // 失败重试次数
                        }
                    })
                    .createMediaSource(MediaItem.fromUri(地址))
            }
            C.CONTENT_TYPE_OTHER -> {
                ProgressiveMediaSource.Factory(factory)
                    .setLoadErrorHandlingPolicy(object : LoadErrorHandlingPolicy {
                        override fun getFallbackSelectionFor(
                            fallbackOptions: FallbackOptions,
                            loadErrorInfo: LoadErrorInfo
                        ): FallbackSelection? {
                            return if (loadErrorInfo.errorCount < 3) null else {
                                FallbackSelection(
                                    LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK,
                                    30000
                                )
                            }
                        }

                        override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
                            return 50 // 重试延迟
                        }

                        override fun onLoadTaskConcluded(loadTaskId: Long) {}
                        override fun getMinimumLoadableRetryCount(dataType: Int): Int {
                            return 10 // 失败重试次数
                        }
                    })
                    .createMediaSource(MediaItem.fromUri(地址))
            }
            else -> {
                ProgressiveMediaSource.Factory(factory)
                    .setLoadErrorHandlingPolicy(object : LoadErrorHandlingPolicy {
                        override fun getFallbackSelectionFor(
                            fallbackOptions: FallbackOptions,
                            loadErrorInfo: LoadErrorInfo
                        ): FallbackSelection? {
                            return null
                        }

                        override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
                            return 10
                        }

                        override fun onLoadTaskConcluded(loadTaskId: Long) {}
                        override fun getMinimumLoadableRetryCount(dataType: Int): Int {
                            return 5
                        }
                    })
                    .createMediaSource(MediaItem.fromUri(contentUri))
            }
        }


    }

    private fun inferContentType(uri: String): Int {
        if (uri.matches(Regex(".*\\.ism(l)?(/manifest(\\(.+\\))?)?")))
            return C.CONTENT_TYPE_SS

        val ext = 地址操作.取后缀(uri) //UUrl.;
        if (ext == "mpd") return C.CONTENT_TYPE_DASH
        else if (ext == "m3u8") return C.CONTENT_TYPE_HLS
        else if (ext == "mp4" || ext == "ts" || ext == "avi" || ext == "flv")
            return C.CONTENT_TYPE_OTHER
        return if (uri.contains("m3u8")) C.CONTENT_TYPE_HLS else C.CONTENT_TYPE_OTHER
    }

    /**
     * Returns a new HttpDataSource factory.
     *
     * @return A new HttpDataSource factory.
     */
    private var mHttpDataSourceFactory: OkHttpDataSource.Factory ? = null
    private fun getHttpDataSourceFactory(
        协议头: Map<String, String>?,
        mUserAgent: String = Util.getUserAgent(context, context.applicationInfo.name)
    )
        : DataSource.Factory {
        if (mHttpDataSourceFactory == null) {
            val sslParams = OkHttpsUtils.getSslSocketFactory(null, null, null)
            val okHttpClient = OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .followSslRedirects(true)
                .followRedirects(true)
                .hostnameVerifier({ hostname, session -> true }) //其他配置
                .build()
            mHttpDataSourceFactory = OkHttpDataSource.Factory(okHttpClient)
            mHttpDataSourceFactory!!.setUserAgent(mUserAgent)
        }

        // 循环操作一篇 确保不重复 添加 User-Agent
        val newHeaders = HashMap<String,String>()

        if (协议头 != null && 协议头.size > 0) {
            for ((key, value) in 协议头) {
                //如果发现用户通过header传递了UA，则强行将HttpDataSourceFactory里面的userAgent字段替换成用户的
                if (key.equals("User-Agent",true)) {
                    mHttpDataSourceFactory!!.setUserAgent(value)
                }else{
                    newHeaders.put(key,value)
                }
            }

            mHttpDataSourceFactory!!.setDefaultRequestProperties(newHeaders)
        }

        return mHttpDataSourceFactory!!
    }

}


